package com.xinshujia.handler;

import com.google.gson.Gson;
import com.xinshujia.config.authorization.MySecurityMetadataSource;
import com.xinshujia.entity.ResourceEntity;
import com.xinshujia.entity.RoleEntity;
import com.xinshujia.entity.UserEntity;
import com.xinshujia.service.ResourceService;
import com.xinshujia.utils.Constants;
import com.xinshujia.utils.GsonUtil;
import com.xinshujia.utils.HttpServletResponseUtil;
import com.xinshujia.utils.JwtUtil;
import com.xinshujia.utils.response.RespResult;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: 野狼上校
 * @create: 2023-03-23  19:01
 * @version: 1.0
 * @description: 认证成功处理器
 */
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private final StringRedisTemplate redisTemplate;
    private final JwtUtil jwtUtil;
    private final ResourceService resourceService;
    private final MySecurityMetadataSource mySecurityMetadataSource;

    public MyAuthenticationSuccessHandler(StringRedisTemplate redisTemplate, JwtUtil jwtUtil, ResourceService resourceService, MySecurityMetadataSource mySecurityMetadataSource) {
        this.redisTemplate = redisTemplate;
        this.jwtUtil = jwtUtil;
        this.resourceService = resourceService;
        this.mySecurityMetadataSource = mySecurityMetadataSource;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
//        com.google.gson.Gson gson = gsonHttpMessageConverter.getGson();
        Gson gson = GsonUtil.googleGson();
        Map<String, String> map = new HashMap<>();
        //1. 获取认证后的用户信息
        UserEntity userEntity = (UserEntity) authentication.getPrincipal();

        // 1.1 把用户信息返回到前端
        UserEntity user = new UserEntity();
        user.setId(userEntity.getId());
        user.setUsername(userEntity.getUsername());
        user.setPhone(userEntity.getPhone());
        user.setRoles(userEntity.getRoles());
        map.put("userInfo", gson.toJson(user));

        //2. 把完整的用户信息保存到redis中 userId作为Key
        String json = gson.toJson(userEntity);
        redisTemplate.opsForValue().set(Constants.USER_INFO + userEntity.getId().toString(), json, 20, TimeUnit.HOURS);

        //3. 认证成功, 使用jwt生成token
        String token = jwtUtil.createToken(userEntity);
        map.put(Constants.LOGIN_TOKEN, token);

        // 4. 当前用户拥有的角色(1个用户可以有多个角色)
        Set<RoleEntity> roles = userEntity.getRoles();

        // 5. 角色能访问的资源
        Set<Long> roleIds = roles.stream().map(RoleEntity::getId).collect(Collectors.toSet());
        // 5.1 根据角色Ids查询资源
        if (!roleIds.isEmpty()){
            Set<ResourceEntity> resourceEntities = resourceService.findResourcesByRIds(roleIds);
            Set<String> resourceUris = resourceEntities.stream().map(ResourceEntity::getResourceUri).collect(Collectors.toSet());

            mySecurityMetadataSource.setResourceUris(resourceUris);
        }


        //7. 返回token到前端
        HttpServletResponseUtil httpServletResponseUtil = new HttpServletResponseUtil();
        RespResult result = RespResult.OK(map);
        httpServletResponseUtil.responseAuthenticationResult(response,result);
    }
}
